package main

import "fmt"

//泛型的函数
func sum[T int | string](a, b T) T {
	return a + b
}

//实现泛型类型的切片
//这里的T表示类型参数 用来表示不同类型的模板
// int | string | float64 这个叫类型约束 表示只能在这几个类型中取一个
// T int | string | float64 就是括号里面的这一套 叫做类型参数列表
// []T 声明一个切片
// 我们管这整个的类型 叫做Slice[T]  它是一个切片泛型
type Slice[T int | string | float64] []T

//同理 我们实现一下泛型的map
type Map[KEY int | string, VALUES string | float64] map[KEY]VALUES

//泛型结构体
//这个Content 的类型可以是上面括号中三个中的一个
type Struct[T string | int | float64] struct {
	Title   string
	Content T
}

//泛型receiver
//这个例子为泛型类型mySlice[T]添加了一个计算成员总和的方法Sum()
//方法的返回参数使用类型形参T
type MySlice[T int | float32] []T

func (s MySlice[T]) Sum() T {
	var sum T
	for _, value := range s {
		sum += value
	}
	return sum
}

func main() {
	a := sum(1, 2)
	b := sum("a", "b")
	fmt.Println(a)
	fmt.Println(b)

	//实现泛型切片
	//在对声明的泛型类型进行实例化时 需要显示的声明实际传入的变量是什么类型的，用它替换T
	var s Slice[int] = []int{1, 2, 3}
	//简写形式
	ss := Slice[string]{"hello", "hi"}
	fmt.Println(ss)
	fmt.Println(s)

	//实例化一个泛型map
	//指定key 和 value 的类型
	var map1 Map[int, string] = map[int]string{
		1: "Hello",
		2: "hi",
	}
	//简写形式
	map2 := Map[string, string]{
		"张三": "坐牢",
		"李四": "枪毙",
	}
	fmt.Println(map1)
	fmt.Println(map2)

	//对泛型结构体进行实例化
	var ms Struct[string]
	ms.Title = "特大消息"
	ms.Content = "震惊"
	fmt.Println(ms)
	//简写形式
	ms1 := Struct[int]{
		Title:   "特大新闻",
		Content: 12,
	}
	fmt.Println(ms1)

	//实例化MySlice
	var sss MySlice[int] = []int{1, 2, 3, 4}
	result := sss.Sum()
	fmt.Println(result)
}
